package com.dev;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.text.Editable;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.InputConnection;
import com.fb.FileBrowserPage;
import com.log;
public class HtmlIndentEditor extends BaseIndentEditor{
	InputConnection currentInputConnection;
	volatile char[] text;
	volatile short[] textWS;
	int primex,primey;
	int lineNumberStart;
	static int tagColor=0xff0000ff;
	static int stringColor=0xffff0000;
	static int commentColor=0xff007f00;
	static  int numColor=0x88999999;
	int scrollX;
	int scrollY;
	MainActivity ma;
    public HtmlIndentEditor(MainActivity ma){
		super(ma);
		this.ma=ma;
		setPadding((int)(6*ma.dp),8,0,0);
		setFocusableInTouchMode(true);
		textPaint.setTypeface(Typeface.MONOSPACE);
		letTextSize((int)ma.dp*ma.shr.getInt(GUISettings.NOTE_TEXT_SIZE,15));
		currentInputConnection=new IC(this,false);
	}
	@Override
	public void letTextSize(int textSize){
		textPaint.setTextSize(textSize);
		lineHeight=textSize;
		primex=lineHeight*2+getPaddingLeft();
		if(text!=null){
			letText(text);
		}
	}
	void atTextChanged(){
	}
	static class DrawCache{
		int ctrl=-1;
		int x;
		int y;
		int index=-1;
		int scrollXMaximum;
		int scrollYMaximum;
		int lineNumber=0;
	}
	public synchronized void letText(char[] text){
		if(text!=null){
			this.text=text;
			if(textWS!=null&&textWS.length>=text.length){
			}else{
				textWS=new short[text.length];
			}
			drawCache=new DrawCache();
			for(int index=0;true;index++){
				if(index<text.length){
					char ch=text[index];
					if(ch!='\n'){
						textWS[index]=(short)textPaint.measureText(Character.toString(ch));
					}
				}else{
					break;
				}
			}
		}else{
			log.alert("On void setText(char[])","parameter on null pointer");
		}
	}
	public void letSelection(int n){
		if(text==null){
			selectionStart=0;
			selectionEnd=0;
		}else if(n>=0&&n<=text.length){
			selectionStart=n;
			selectionEnd=n;
		}else{
			log.alert("无效的参数","selection start:"+selectionStart+"\nselection end:"+selectionEnd);
		}
	}
	public void letSelection(int a,int b){
		if(a<0){
			a=0;
			if(b<0){
				b=0;
			}else if(b>text.length){
				b=text.length;
			}
			selectionStart=a;
			selectionEnd=b;
		}else if(a>text.length){
			a=text.length;
			if(b<0){
				b=0;
			}else if(b>text.length){
				b=text.length;
			}
			selectionStart=a;
			selectionEnd=b;
		}else if(b<0){
			b=0;
			selectionStart=a;
			selectionEnd=b;
		}else if(b>text.length){
			b=text.length;
			selectionStart=a;
			selectionEnd=b;
		}else{
			selectionStart=a;
			selectionEnd=b;
		}
	}
	void repl(int a,int b,char[] s){
		//log.alert(a+":"+b);
		if(a>b){
			int n=a;
			a=b;
			b=n;
		}
		if(a<0||a>text.length||b<0||b>text.length){
			log.alert("无效的参数","selection start:"+selectionStart+"\nselection end:"+selectionEnd);
			return;
		}
		if(s!=null){
			char[] textWill=new char[text.length+s.length-(b-a)];
			for(int index=0;index<a;index++){
				textWill[index]=text[index];
			}
			for(int textWill_index=a,s_index=0;s_index<s.length;textWill_index++,s_index++){
				textWill[textWill_index]=s[s_index];
			}
			for(int org=a+s.length,offs=0;offs+org<textWill.length;offs++){
				textWill[org+offs]=text[b+offs];
			}
			letText(textWill);
		}else{
			char[] textWill=new char[text.length-(b-a)];
			for(int n=0;n<a;n++){
				textWill[n]=text[n];
			}
			for(int ia=a,ib=b;ia<textWill.length&&ib<text.length;ia++,ib++){
				textWill[ia]=text[ib];
			}
			letText(textWill);
		}
		invalidate();
	}
	@Override
	public boolean dispatchKeyShortcutEvent(KeyEvent event) {
		return super.dispatchKeyShortcutEvent(event);
	}
	@Override
	public boolean dispatchKeyEvent(KeyEvent event){
		switch(event.getKeyCode()){
			case KeyEvent.KEYCODE_VOLUME_UP:
				return false;
			case KeyEvent.KEYCODE_VOLUME_DOWN:
				return false;
			case KeyEvent.KEYCODE_VOLUME_MUTE:
				return false;
			case KeyEvent.KEYCODE_POWER:
				return false;
			case KeyEvent.KEYCODE_TAB:
				if(event.getAction()==KeyEvent.ACTION_DOWN){
					currentInputConnection.commitText("\t",1);
				}
				return true;
			case KeyEvent.KEYCODE_DEL:
				if(event.getAction()==KeyEvent.ACTION_DOWN){
					if(currentInputConnection!=null){
						currentInputConnection.deleteSurroundingText(1,0);
					}
				}
				return true;
			case KeyEvent.KEYCODE_ENTER:
				if(event.getAction()==KeyEvent.ACTION_DOWN){
					if(currentInputConnection!=null){
						currentInputConnection.sendKeyEvent(event);
					}
				}
				return true;
			default:
				return true;
		}
	}
	boolean onTextChanged_ignoreChange=false;
	@Override
	protected void onTextChanged(CharSequence text,int start,int lengthBefore,int lengthAfter){
		super.onTextChanged(text,start,lengthBefore,lengthAfter);
		//setText("");
		if(onTextChanged_ignoreChange){
			onTextChanged_ignoreChange=false;
			return;
		}
		//if(true)return;
		Editable ed=getEditableText();
		if(ed!=null){
			String s=getEditableText().toString();
			onTextChanged_ignoreChange=true;
			setText("");
			if(!s.isEmpty()){
				if(currentInputConnection!=null){
					currentInputConnection.commitText(s,1);//s.length());
				}
			}
		}
	}
	@Override
	protected void onAttachedToWindow(){
		super.onAttachedToWindow();
		/*if(text!=null){
			letTextSize((int)ma.dp*ma.shr.getInt(GUISettings.NOTE_TEXT_SIZE,15));
			setText(text);
		}*/
		//setBackgroundColor(ma.shr.getInt("handwrittenbgcolor",defaultbgcolor));
	}
	@Override
	protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec){
		super.onMeasure(widthMeasureSpec,heightMeasureSpec);
		primex=getPaddingLeft()+lineHeight*2;
		primey=getPaddingTop();
		lineNumberStart=getPaddingLeft();
	}
	@Override
	protected void onVisibilityChanged(View changedView,int visibility){
		super.onVisibilityChanged(changedView,visibility);
		if(visibility==View.VISIBLE){
			if(hasFocus()){
				if(tcv.getState()!=Thread.State.NEW){
					tcv=new TurnCursorVisibility();
					tcv.start();
				}else{
					tcv.finished=true;
					tcv=new TurnCursorVisibility();
					tcv.start();
				}
			}else{
				tcv.finished=true;
				showCursor=true;
				invalidate();
			}
		}else{
			tcv.finished=true;
		}
	}
	@Override
	protected void onFocusChanged(boolean gainFocus,int direction,Rect previouslyFocusedRect){
		super.onFocusChanged(gainFocus,direction,previouslyFocusedRect);
		if(hasFocus()){
			tcv.finished=true;
			tcv=new TurnCursorVisibility();
			tcv.start();
		}else{
			tcv.finished=true;
			if(!showCursor){
				showCursor=true;
				invalidate();
			}
		}
	}
	/*@Override
	public InputConnection onCreateInputConnection(EditorInfo outAttrs){
		return new IC(this,false);
	}*/
	InputConnectionProxy icp;
	class InputConnectionProxy extends BaseInputConnection{
		InputConnection former;
		InputConnectionProxy(InputConnection former){
			super(HtmlIndentEditor.this,false);
			this.former=former;
		}
        
		@Override
		public boolean deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) {
			return false;
		}
		@Override
		public boolean deleteSurroundingText(int beforeLength, int afterLength) {
			int a=selectionStart;
			int b=selectionEnd;
			if(a==b){
				int start=a-beforeLength;
				int end=a;
				if(start<0)return false;
				repl(start,end,null);
				letSelection(start,start);
				start=selectionStart;
				end=selectionStart+afterLength;
				if(end>=text.length){atTextChanged();return false;}
				repl(start,end,null);
			}else{
				repl(a,b,null);
				if(a<=b){
					selectionEnd=selectionStart;
				}else{
					selectionStart=selectionEnd;
				}
			}
			atTextChanged();
			return true;
		}
	}
	DrawCache drawCache;
	Point touchDown=new Point();
	Point touchDown2=null;
	Point scrollSaved=new Point();
	Point scrollSaved_touchSaved=new Point();
	long touchDownTime;
	long recentTouchTime;
	Point recentTouch=new Point();
	boolean fingerMoved=false;
	boolean fingerPressed=false;
	boolean scaled;
	float fingerDistanceSaved;
	int fingerMovedOrientation;
	int textSizeSaved;
	WaitLongClick wlc;
	float speed;
	float speedx;
	float speedy;
	InertiaScroll inertiaScroll;
	@Override
	public boolean dispatchTouchEvent(MotionEvent event){
		int ex=(int)event.getX();
		int ey=(int)event.getY();
		int rx=(int)event.getRawX();
		int ry=(int)event.getRawY();
		switch(event.getActionMasked()){
			case MotionEvent.ACTION_DOWN:
				scrollSaved.x=scrollX;
				scrollSaved.y=scrollY;
				scrollSaved_touchSaved.x=rx;
				scrollSaved_touchSaved.y=ry;
				scaled=false;
				touchDown.x=ex;
				touchDown.y=ey;
				fingerMoved=false;
				touchDownTime=System.currentTimeMillis();
				fingerPressed=true;
				if(wlc!=null){
					wlc.interrupt();
				}
				if(inertiaScroll!=null){
					inertiaScroll.interrupt();
				}
				wlc=new WaitLongClick();
				wlc.start();
				wlc.lastTouch.x=ex;
				wlc.lastTouch.y=ey;
				recentTouchTime=System.currentTimeMillis();
				recentTouch.x=ex;
				recentTouch.y=ey;
				break;
			case MotionEvent.ACTION_POINTER_DOWN:
				//log.alert("multi touch");
				{
					wlc.waited=true;
					wlc.interrupt();
					textSizeSaved=(int)textPaint.getTextSize();
					int ex1=(int)event.getX(0);
					int ey1=(int)event.getY(0);
					int ex2=(int)event.getX(1);
					int ey2=(int)event.getY(1);
					int xdiff=Math.abs(ex1-ex2);
					int ydiff=Math.abs(ey1-ey2);
					float len=(int)Math.sqrt(xdiff*xdiff+ydiff*ydiff);
					fingerDistanceSaved=len;
				}
				/*if(touchDown2==null){
					touchDown2=new Point();
					/*touchDown2.x=(int)event.getX(event.getActionIndex());
					touchDown2.y=(int)event.getY(event.getActionIndex());
					int xdiff=Math.abs(touchDown2.x-touchDown.x);
					int ydiff=Math.abs(touchDown2.y-touchDown.y);
					//(int)Math.sqrt(xdiff*xdiff+ydiff*ydiff);
				}*/
				break;
			case MotionEvent.ACTION_MOVE:
				if(event.getPointerCount()==1){
					if(fingerMoved){
						if(fingerMovedOrientation==0){
							int scrollxWill=scrollSaved.x-(rx-scrollSaved_touchSaved.x);
							if(scrollxWill<=0){
								scrollSaved.x=0;
								scrollSaved_touchSaved.x=rx;
								scrollX=0;
								invalidate();
							}else if(scrollxWill>=drawCache.scrollXMaximum){
								scrollSaved.x=drawCache.scrollXMaximum;
								scrollSaved_touchSaved.x=rx;
								scrollX=drawCache.scrollXMaximum;
								invalidate();
							}else{
								scrollX=scrollxWill;
								invalidate();
							}
							long dt=System.currentTimeMillis()-recentTouchTime;
							if(dt>0){
								float fingerMovedSpeed_will=(ex-recentTouch.x)/dt;
								speed=(fingerMovedSpeed_will+speed)/2;
							}
						}else if(fingerMovedOrientation==1){
							int scrollyWill=scrollSaved.y-(ry-scrollSaved_touchSaved.y);
							//log.alert("scrolYMaximum:"+scrollYMaximum);
							if(scrollyWill<=0){
								scrollSaved.y=0;
								scrollSaved_touchSaved.y=ry;
								scrollY=0;
								invalidate();
							}else if(scrollyWill>=drawCache.scrollYMaximum){
								scrollSaved.y=drawCache.scrollYMaximum;
								scrollSaved_touchSaved.y=ry;
								scrollY=drawCache.scrollYMaximum;
								invalidate();
							}else{
								scrollY=scrollyWill;
								invalidate();
							}
							long dTime=System.currentTimeMillis()-recentTouchTime;
							if(dTime>0){
								float fingerMovedSpeed_will=(ey-recentTouch.y)/dTime;
								speed=(fingerMovedSpeed_will+speed)/2;
							}
						}else{
							int scrollxWill=scrollSaved.x-(rx-scrollSaved_touchSaved.x);
							int scrollyWill=scrollSaved.y-(ry-scrollSaved_touchSaved.y);
							if(scrollxWill<=0){
								scrollSaved.x=0;
								scrollSaved_touchSaved.x=rx;
								if(scrollyWill<=0){
									scrollSaved.y=0;
									scrollSaved_touchSaved.y=ry;
									scrollX=0;
									scrollY=0;
									invalidate();
								}else if(scrollyWill>=drawCache.scrollYMaximum){
									scrollSaved.y=drawCache.scrollYMaximum;
									scrollSaved_touchSaved.y=ry;
									scrollX=0;
									scrollY=drawCache.scrollYMaximum;
									invalidate();
								}else{
									scrollX=scrollxWill;
									scrollY=scrollyWill;
									invalidate();
								}
							}else if(scrollxWill>=drawCache.scrollXMaximum){
								scrollSaved.x=drawCache.scrollXMaximum;
								scrollSaved_touchSaved.x=rx;
								if(scrollyWill<=0){
									scrollSaved.y=0;
									scrollSaved_touchSaved.y=ry;
									scrollX=drawCache.scrollXMaximum;
									scrollY=0;
									invalidate();
								}else if(scrollyWill>=drawCache.scrollYMaximum){
									scrollSaved.y=drawCache.scrollYMaximum;
									scrollSaved_touchSaved.y=ry;
									scrollX=drawCache.scrollXMaximum;
									scrollY=drawCache.scrollYMaximum;
									invalidate();
								}else{
									scrollX=drawCache.scrollXMaximum;
									scrollY=scrollyWill;
									invalidate();
								}
							}else if(scrollyWill<=0){
								scrollSaved.y=0;
								scrollSaved_touchSaved.y=ry;
								scrollX=scrollxWill;
								scrollY=0;
								invalidate();
							}else if(scrollyWill>=drawCache.scrollYMaximum){
								scrollSaved.y=drawCache.scrollYMaximum;
								scrollSaved_touchSaved.y=ry;
								scrollX=scrollxWill;
								scrollY=drawCache.scrollYMaximum;
								invalidate();
							}else{
								scrollX=scrollxWill;
								scrollY=scrollyWill;
								invalidate();
							}
						}
					}else{
						int dx=Math.abs(ex-touchDown.x);
						int dy=Math.abs(ey-touchDown.y);
						if(dx>5||dy>5){
							fingerMoved=true;wlc.interrupt();
							long dTime=System.currentTimeMillis()-recentTouchTime;
							if(dx>dy){
								fingerMovedOrientation=0;//水平移动
								if(dTime>0){
									speed=(ex-touchDown.x)/dTime;
								}
							}else if(dx<dy){//垂直移动
								//log.alert("ver");
								fingerMovedOrientation=1;
								if(dTime>0){
									speed=(ey-touchDown.y)/dTime;
								}
							}else{//方向不明
								fingerMovedOrientation=-1;
							}
						}
					}
					if(!wlc.waited){
						wlc.lastTouch.x=ex;
						wlc.lastTouch.y=ey;
					}
					recentTouchTime=System.currentTimeMillis();
					recentTouch.x=ex;
					recentTouch.y=ey;
				}else if(fingerDistanceSaved!=0){
					scaled=true;
					int ex1=(int)event.getX(0);
					int ey1=(int)event.getY(0);
					int ex2=(int)event.getX(1);
					int ey2=(int)event.getY(1);
					int xdiff=Math.abs(ex1-ex2);
					int ydiff=Math.abs(ey1-ey2);
					float len=(int)Math.sqrt(xdiff*xdiff+ydiff*ydiff);
					float scale=len/fingerDistanceSaved;
					int textSizeWill=(int)(textSizeSaved*scale);
					if(textSizeWill<=minTextSize){
						letTextSize(minTextSize);
					}else if(textSizeWill>maxTextSize){
						letTextSize(maxTextSize);
					}else{
						letTextSize(textSizeWill);
					}
					invalidate();
				}else{
					//log.alert("0");
				}
				break;
			case MotionEvent.ACTION_UP:
				//if(highlight==HighlightType.JAVA)log.alert("2333");
				touchDown2=null;
				fingerPressed=false;
				wlc.interrupt();
				if(fingerMoved){
					inertiaScroll=new InertiaScroll();
					inertiaScroll.orientation=fingerMovedOrientation;
					inertiaScroll.initialSpeed=speed;
					inertiaScroll.initialScrollX=scrollX;
					inertiaScroll.initialScrollY=scrollY;
					inertiaScroll.start();
				}else{
					if(wlc.waited){
					}else{
						ma.gui.removeViewAt(ma.gui.titleIndex);
                        ma.gui.addView(ma.gui.titlebar,ma.gui.titleIndex,ma.gui.titlebarlp);
						if(ex>=0&&ex<getWidth()&&ey>=0&&ey<getHeight()){
							if(requestFocus()){
								if(canShowSoftInput)
									imm.showSoftInput(this,0);
								if(text!=null&&textWS!=null){
									int rr=calculClicked(ex+scrollX,ey+scrollY);
									if(rr>=0){
										//log.alert("click:"+rr);
										letSelection(rr);
										showCursor=true;
										tcv.againWait=true;
										tcv.interrupt();
										invalidate();
									}
								}
							}
						}
					}
				}
				break;
			case MotionEvent.ACTION_CANCEL:
				fingerPressed=false;
				touchDown2=null;
				wlc.interrupt();
				if(fingerMoved){
				}else{
					if(ex>=0&&ex<=getWidth()&&ey>=0&&ey<=getHeight()){
						if(requestFocus()){
							if(canShowSoftInput)
								imm.showSoftInput(this,0);
						}
					}
				}
		}
		return true;
	}
	int calculClicked(int ex,int ey){
		int tablen=(int)textPaint.measureText(tabWidth);
		for(int index=drawCache.index,x=drawCache.x,y=drawCache.y,limLeft=drawCache.x;true;index++){
			if(index<text.length){
				char ch=text[index];
				if(ch=='\n'){
					int ywill=y+lineHeight;
					if(ex>x&&ey>=y&&ey<ywill){
						return index;
					}
					limLeft=primex;
					x=primex;
					y=ywill;
				}else if(ch=='\t'){
					int xwill=((x-primex)/tablen+1)*tablen+primex;
					int xlim=x+(xwill-x)/2;
					if(ex>limLeft&&ex<xlim&&ey>=y&&ey<y+lineHeight){
						return index;
					}
					x=xwill;
					limLeft=xlim;
				}else{
					int advance=textWS[index];
					int xWill=x+advance;
					int xlim=x+advance/2;
					if(ex>limLeft&&ex<xlim&&ey>y&&ey<y+lineHeight){
						return index;
					}
					x=xWill;
					limLeft=xlim;
				}
			}else{
				if(ey>y){
					return text.length;
				}
				break;
			}
		}
		return -1;
	}
	@Override
	public void draw(Canvas canvas){
		if(text!=null&&textWS!=null){
			int tablen=(int)textPaint.measureText(tabWidth);
			Paint cursor=new Paint();
			int cursorWidth=Math.round(textPaint.getTextSize()/13);
			if(cursorWidth<=0)cursorWidth=1;
			cursor.setStrokeWidth(cursorWidth);
			textPaint.setColor(textColor);
			Paint hanghao=new Paint();
			Paint xz=new Paint();
			xz.setColor(selectionbgcolor);
			hanghao.setColor(numColor);
			hanghao.setTextSize(textPaint.getTextSize()*0.75f);
			final int baseline=(int)(lineHeight*0.88);
			final int jx=(int)((baseline-(0.75*baseline))/2+(baseline*0.75));
			final int vw=getWidth();
			final int vh=getHeight();
			final int yInvisible=scrollY-lineHeight;
			final int yOverflowMin=scrollY+vh;
			canvas.translate(-scrollX,-scrollY);
			if(drawCache.index<0){
				drawCache.index=0;
				drawCache.x=primex;
				drawCache.y=primey;
				drawCache.lineNumber=1; 
				drawCache.ctrl=-1;
			}
			int x=drawCache.x;
			int y=drawCache.y;
			int line=drawCache.lineNumber;
			int ctrl=drawCache.ctrl;
			if(showSpaceChar){
				int dotSize=(int)(lineHeight*0.3);
				outmost:
				for(int index=drawCache.index;true;index++){//不折行的绘制纯文本
					if(index<text.length){
						if(y<=yInvisible){//字符在视口之外
							char ch=text[index];
							if(ch=='\n'){
								line+=1;
								y+=lineHeight;
								if(ctrl==1){
									ctrl=2;
								}else if(ctrl==3){
									ctrl=4;
								}
							}else if(ch=='<'){
								if(ctrl<0){
									int nn=index+1;
									char cc=text[nn];
									if(cc=='!'){
										if(++nn<text.length){
											cc=text[nn];
											if(cc=='-'){
												if(++nn<text.length){
													cc=text[nn];
													if(cc=='-'){
														ctrl=10;
														textPaint.setColor(commentColor);
													}else{
														ctrl=1;
														textPaint.setColor(tagColor);
													}
												}else{
													ctrl=1;
													textPaint.setColor(tagColor);
												}
											}else{
												ctrl=1;
												textPaint.setColor(tagColor);
											}
										}else{
											ctrl=1;
											textPaint.setColor(tagColor);
										}
									}else{
										ctrl=1;
										textPaint.setColor(tagColor);
									}
									//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
								}
							}else if(ch=='\''){
								if(ctrl==5){
									ctrl=4;
								}else if(ctrl!=0&&ctrl>0&&ctrl!=6&&ctrl<10){
									ctrl=5;
									textPaint.setColor(stringColor);
								}
							}else if(ch=='\"'){
								if(ctrl<10){
									if(ctrl==0){
										ctrl=4;
										//textPaint.setColor(textColor);
									}else if(ctrl>0){
										ctrl=0;
										//textPaint.setColor(stringColor);
										//textPaint.setStyle(Paint.Style.FILL);
									}
								}
							}else if(ch=='>'){
								if(ctrl==14){
									int nn=index-1;
									char cc=text[nn];
									if(cc=='-'){
										if(--nn>=0){
											cc=text[nn];
											if(cc=='-'){
												ctrl=-1;
											}
										}
									}
								}else if(ctrl<10){
									ctrl=-1;
									textPaint.setColor(tagColor);
								}
							}else if(ch=='-'){
								if(ctrl>=10&&ctrl<14){
									ctrl++;
								}
							}else if(ch!=' '&&ch!='\t'){
								if(ctrl==1){ctrl=2;}
								if(ctrl==3){ctrl=4;}
							}else{
								if(ctrl==2||ctrl==1){ctrl=3;}
							}
							continue;
						}else{
							//字符在视口之内，开始绘制
							if(y>drawCache.scrollYMaximum)drawCache.scrollYMaximum=y;
							if(x>drawCache.scrollXMaximum)drawCache.scrollXMaximum=x;
							canvas.drawText(String.format("%03d",line),lineNumberStart,y+jx,hanghao);
							for(;true;index++){
								if(index<text.length){
									for(int ii=index;true;ii++){
										if(ii<text.length){
											char ch=text[ii];
											if(ii>=selectionEnd){
												if(ii==selectionEnd){
													int i=textPaint.getColor();
													textPaint.setStyle(Paint.Style.FILL);
													textPaint.setColor(currentLineHighlight);
													canvas.drawRect(scrollX,y,vw+scrollX,y+lineHeight,textPaint);
													textPaint.setColor(i);
												}
												for(;true;index++){//画出余下行
													if(index==selectionStart){//画光标
														if(index==selectionEnd){
															if(showCursor){
																canvas.drawLine(x,y,x,y+lineHeight,cursor);
															}
														}
													}
													if(x>drawCache.scrollXMaximum)drawCache.scrollXMaximum=x;
													if(index<text.length){
														ch=text[index];
														int xWill=0;
														if(ch=='\n'){
															line++;
															y+=lineHeight;
															x=primex;
															canvas.drawText(String.format("%03d",line),lineNumberStart,y+jx,hanghao);
															if(ctrl==1){
																ctrl=2;
															}else if(ctrl==3){
																ctrl=4;
															}
															int yy=y+lineHeight;
															if(yy>drawCache.scrollYMaximum){
																drawCache.scrollYMaximum=yy;
															}
															if(index>=selectionStart&&index<selectionEnd){//换行符是被选中的，画出它的背景高亮
																canvas.drawRect(x,y,vw+scrollX,y+lineHeight,xz);
															}else if(index>=selectionEnd&&index<selectionStart){
																canvas.drawRect(x,y,vw+scrollX,y+lineHeight,xz);
															}
															if(y>=yOverflowMin){
																break outmost;
															}
														}else if(ch=='\t'){
															xWill=((x-primex)/tablen+1)*tablen+primex;
															if(index>=selectionStart&&index<selectionEnd){//画选中高亮
																canvas.drawRect(x,y,xWill,y+lineHeight,xz);
															}else if(index>=selectionEnd&&index<selectionStart){
																canvas.drawRect(x,y,xWill,y+lineHeight,xz);
															}
															x=xWill;
															//if(x>drawCache.scrollXMaximum)drawCache.scrollXMaximum=x;
															if(ctrl==1){
																ctrl=2;
															}else if(ctrl==3){
																ctrl=4;
															}
														}else if(ch==' '){
															if(ctrl==1){
																ctrl=2;
															}else if(ctrl==3){
																ctrl=4;
															}
															int advance=textWS[index];
															xWill=x+advance;
															if(index>=selectionStart&&index<selectionEnd){//画选中高亮
																canvas.drawRect(x,y,xWill,y+lineHeight,xz);
															}else if(index>=selectionEnd&&index<selectionStart){
																canvas.drawRect(x,y,xWill,y+lineHeight,xz);
															}
															int i=textPaint.getColor();
															textPaint.setColor(0x77888888);
															textPaint.setStyle(Paint.Style.FILL);
															canvas.drawCircle(x+advance/2,y+lineHeight/2,dotSize,textPaint);
															x=xWill;
															textPaint.setColor(i);
														}else{
															if(ch=='='){
																if(ctrl==1||ctrl==2||ctrl==3||ctrl==4){
																	//int i=textPaint.getColor();
																	textPaint.setColor(tagColor);
																	/*int advance=textWS[index];
																	xWill=x+advance;
																	if(index>=selectionStart&&index<selectionEnd){//画选中高亮
																		canvas.drawRect(x,y,xWill,y+lineHeight,xz);
																	}else if(index>=selectionEnd&&index<selectionStart){
																		canvas.drawRect(x,y,xWill,y+lineHeight,xz);
																	}
																	canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
																	x=xWill;
																	textPaint.setColor(i);
																	if(x>drawCache.scrollXMaximum){
																		drawCache.scrollXMaximum=x;
																	}
																	continue;*/
																}
															}else if(ch=='-'){
																if(ctrl>=10&&ctrl<14){
																	ctrl++;
																}
															}else if(ch=='<'){
																if(ctrl<0){
																	int nn=index+1;
																	char cc=text[nn];
																	if(cc=='!'){
																		if(++nn<text.length){
																			cc=text[nn];
																			if(cc=='-'){
																				if(++nn<text.length){
																					cc=text[nn];
																					if(cc=='-'){
																						ctrl=10;
																						textPaint.setColor(commentColor);
																					}else{
																						ctrl=1;
																						textPaint.setColor(tagColor);
																					}
																				}else{
																					ctrl=1;
																					textPaint.setColor(tagColor);
																				}
																			}else{
																				ctrl=1;
																				textPaint.setColor(tagColor);
																			}
																		}else{
																			ctrl=1;
																			textPaint.setColor(tagColor);
																		}
																	}else{
																		ctrl=1;
																		textPaint.setColor(tagColor);
																	}
																	//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
																}
															}else if(ch=='>'){
																if(ctrl==14){
																	int nn=index-1;
																	char cc=text[nn];
																	if(cc=='-'){
																		if(--nn>=0){
																			cc=text[nn];
																			if(cc=='-'){
																				ctrl=-1;
																				int advance=textWS[index];
																				xWill=x+advance;
																				if(index>=selectionStart&&index<selectionEnd){//画选中高亮
																					canvas.drawRect(x,y,xWill,y+lineHeight,xz);
																				}else if(index>=selectionEnd&&index<selectionStart){
																					canvas.drawRect(x,y,xWill,y+lineHeight,xz);
																				}
																				canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
																				x=xWill;
																				//if(x>drawCache.scrollXMaximum)drawCache.scrollXMaximum=x;
																				textPaint.setColor(textColor);
																				continue;
																			}
																		}
																	}
																}else if(ctrl<10){
																	ctrl=-1;
																	int advance=textWS[index];
																	xWill=x+advance;
																	if(index>=selectionStart&&index<selectionEnd){//画选中高亮
																		canvas.drawRect(x,y,xWill,y+lineHeight,xz);
																	}else if(index>=selectionEnd&&index<selectionStart){
																		canvas.drawRect(x,y,xWill,y+lineHeight,xz);
																	}
																	textPaint.setColor(tagColor);
																	canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
																	x=xWill;
																	//if(x>drawCache.scrollXMaximum)drawCache.scrollXMaximum=x;
																	textPaint.setColor(textColor);
																	continue;
																}
																//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
															}else if(ch=='\"'){
																if(ctrl<10){
																	if(ctrl==0){
																		ctrl=4;
																		int advance=textWS[index];
																		xWill=x+advance;
																		if(index>=selectionStart&&index<selectionEnd){//画选中高亮
																			canvas.drawRect(x,y,xWill,y+lineHeight,xz);
																		}else if(index>=selectionEnd&&index<selectionStart){
																			canvas.drawRect(x,y,xWill,y+lineHeight,xz);
																		}
																		canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
																		x=xWill;
																		//if(x>drawCache.scrollXMaximum)drawCache.scrollXMaximum=x;
																		textPaint.setColor(textColor);
																		continue;
																		//textPaint.setColor(textColor);
																	}else if(ctrl>0&&ctrl!=5&&ctrl!=6){
																		ctrl=0;
																		textPaint.setColor(stringColor);
																		//textPaint.setStyle(Paint.Style.FILL);
																	}
																}
															}else if(ch=='\''){
																if(ctrl==5){
																	ctrl=4;
																	int advance=textWS[index];
																	xWill=x+advance;
																	if(index>=selectionStart&&index<selectionEnd){//画选中高亮
																		canvas.drawRect(x,y,xWill,y+lineHeight,xz);
																	}else if(index>=selectionEnd&&index<selectionStart){
																		canvas.drawRect(x,y,xWill,y+lineHeight,xz);
																	}
																	canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
																	x=xWill;
																	//if(x>drawCache.scrollXMaximum)drawCache.scrollXMaximum=x;
																	textPaint.setColor(textColor);
																	continue;
																}else if(ctrl!=0&&ctrl>0&&ctrl!=6&&ctrl<10){
																	ctrl=5;
																	textPaint.setColor(stringColor);
																}
															}else if(ch=='/'){
																if(ctrl<10){
																	if(ctrl>0&&ctrl!=6&&ctrl!=5){
																		textPaint.setColor(tagColor);
																		//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
																	}
																}
															}else if(ctrl<0){
																textPaint.setColor(textColor);
																//textPaint.setStyle(Paint.Style.FILL);
															}else if(ctrl==1){
																ctrl=3;
																textPaint.setColor(tagColor);
																//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
															}else if(ctrl==2){
																ctrl=3;
																textPaint.setColor(tagColor);
																//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
															}else if(ctrl==3){
																textPaint.setColor(tagColor);
																//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
															}else if(ctrl==4){
																textPaint.setColor(textColor);
																//textPaint.setStyle(Paint.Style.FILL);
															}
															int advance=textWS[index];
															xWill=x+advance;
															if(index>=selectionStart&&index<selectionEnd){//画选中高亮
																canvas.drawRect(x,y,xWill,y+lineHeight,xz);
															}else if(index>=selectionEnd&&index<selectionStart){
																canvas.drawRect(x,y,xWill,y+lineHeight,xz);
															}
															canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
															x=xWill;
														}
														//if(x>drawCache.scrollXMaximum)drawCache.scrollXMaximum=x;
													}else{
														break;
													}
												}
												break outmost;
											}else if(ch=='\n'){
												break;
											}
										}else{//默认最后一行高亮
											textPaint.setStyle(Paint.Style.FILL);
											textPaint.setColor(currentLineHighlight);
											canvas.drawRect(scrollX,y,vw+scrollX,y+lineHeight,textPaint);
											textPaint.setColor(textColor);
											break;
										}
									}
									for(;true;index++){//画出一行
										if(index==selectionStart){//画光标
											if(index==selectionEnd){
												if(showCursor){
													canvas.drawLine(x,y,x,y+lineHeight,cursor);
												}
											}
										}
										if(index<text.length){
											char ch=text[index];
											int xWill=0;
											if(ch=='\n'){
												line++;
												y+=lineHeight;
												x=primex;
												canvas.drawText(String.format("%03d",line),lineNumberStart,y+jx,hanghao);
												if(ctrl==1){
													ctrl=2;
												}else if(ctrl==3){
													ctrl=4;
												}
												if(index>=selectionStart&&index<selectionEnd){//换行符是被选中的，画出它的背景高亮
													canvas.drawRect(x,y,vw+scrollX,y+lineHeight,xz);
												}else if(index>=selectionEnd&&index<selectionStart){
													canvas.drawRect(x,y,vw+scrollX,y+lineHeight,xz);
												}
												int yy=y+lineHeight;
												if(yy>drawCache.scrollYMaximum){
													drawCache.scrollYMaximum=yy;
												}
												if(y>=yOverflowMin){
													break outmost;
												}
												break;
											}else if(ch=='\t'){
												xWill=((x-primex)/tablen+1)*tablen+primex;
												if(ctrl==1){
													ctrl=2;
												}else if(ctrl==3){
													ctrl=4;
												}
												if(index>=selectionStart&&index<selectionEnd){//换行符是被选中的，画出它的背景高亮
													canvas.drawRect(x,y,xWill,y+lineHeight,xz);
												}else if(index>=selectionEnd&&index<selectionStart){
													canvas.drawRect(x,y,xWill,y+lineHeight,xz);
												}
												x=xWill;
											}else if(ch==' '){
												int advance=textWS[index];
												xWill=x+advance;
												int i=textPaint.getColor();
												textPaint.setColor(0x77888888);
												textPaint.setStyle(Paint.Style.FILL);
												canvas.drawCircle(x+advance/2,y+lineHeight/2,dotSize,textPaint);
												textPaint.setColor(i);
												if(index>=selectionStart&&index<selectionEnd){//换行符是被选中的，画出它的背景高亮
													canvas.drawRect(x,y,xWill,y+lineHeight,xz);
												}else if(index>=selectionEnd&&index<selectionStart){
													canvas.drawRect(x,y,xWill,y+lineHeight,xz);
												}
												x=xWill;
												if(ctrl==1){
													ctrl=2;
												}else if(ctrl==3){
													ctrl=4;
												}
											}else{
												if(ch=='='){
													if(ctrl==1||ctrl==2||ctrl==3||ctrl==4){
														textPaint.setColor(tagColor);
														//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
													}
												}else if(ch=='-'){
													if(ctrl>=10&&ctrl<14){
														ctrl++;
													}
												}else if(ch=='<'){
													if(ctrl<0){
														int nn=index+1;
														char cc=text[nn];
														if(cc=='!'){
															if(++nn<text.length){
																cc=text[nn];
																if(cc=='-'){
																	if(++nn<text.length){
																		cc=text[nn];
																		if(cc=='-'){
																			ctrl=10;
																			textPaint.setColor(commentColor);
																		}else{
																			ctrl=1;
																			textPaint.setColor(tagColor);
																		}
																	}else{
																		ctrl=1;
																		textPaint.setColor(tagColor);
																	}
																}else{
																	ctrl=1;
																	textPaint.setColor(tagColor);
																}
															}else{
																ctrl=1;
																textPaint.setColor(tagColor);
															}
														}else{
															ctrl=1;
															textPaint.setColor(tagColor);
														}
														//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
													}
												}else if(ch=='>'){
													if(ctrl==14){
														int nn=index-1;
														char cc=text[nn];
														if(cc=='-'){
															if(--nn>=0){
																cc=text[nn];
																if(cc=='-'){
																	ctrl=-1;
																	int advance=textWS[index];
																	xWill=x+advance;
																	if(index>=selectionStart&&index<selectionEnd){//换行符是被选中的，画出它的背景高亮
																		canvas.drawRect(x,y,xWill,y+lineHeight,xz);
																	}else if(index>=selectionEnd&&index<selectionStart){
																		canvas.drawRect(x,y,xWill,y+lineHeight,xz);
																	}
																	canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
																	x=xWill;
																	textPaint.setColor(textColor);
																	continue;
																}
															}
														}
													}else if(ctrl<10){
														ctrl=-1;
														int advance=textWS[index];
														xWill=x+advance;
														textPaint.setColor(tagColor);
														canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
														x=xWill;
														textPaint.setColor(textColor);
														continue;
													}
													//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
												}else if(ch=='\"'){
													if(ctrl<10){
														if(ctrl==0){
															ctrl=4;
															int advance=textWS[index];
															xWill=x+advance;
															canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
															x=xWill;
															textPaint.setColor(textColor);
															continue;
															//textPaint.setColor(textColor);
														}else if(ctrl>0&&ctrl!=5&&ctrl!=6){
															ctrl=0;
															textPaint.setColor(stringColor);
															//textPaint.setStyle(Paint.Style.FILL);
														}
													}
												}else if(ch=='\''){
													if(ctrl==5){
														ctrl=4;
														int advance=textWS[index];
														xWill=x+advance;
														canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
														x=xWill;
														textPaint.setColor(textColor);
														continue;
													}else if(ctrl!=0&&ctrl>0&&ctrl!=6&&ctrl<10){
														ctrl=5;
														textPaint.setColor(stringColor);
													}
												}else if(ch=='/'){
													if(ctrl<10){
														if(ctrl>0&&ctrl!=6&&ctrl!=5){
															textPaint.setColor(tagColor);
															//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
														}
													}
												}else if(ctrl<0){
													textPaint.setColor(textColor);
													//textPaint.setStyle(Paint.Style.FILL);
												}else if(ctrl==1){
													ctrl=3;
													textPaint.setColor(tagColor);
													//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
												}else if(ctrl==2){
													ctrl=3;
													textPaint.setColor(tagColor);
													//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
												}else if(ctrl==3){
													textPaint.setColor(tagColor);
													//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
												}else if(ctrl==4){
													textPaint.setColor(textColor);
													//textPaint.setStyle(Paint.Style.FILL);
												}
												int advance=textWS[index];
												int xwill=x+advance;
												canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
												if(index>=selectionStart&&index<selectionEnd){//换行符是被选中的，画出它的背景高亮
													canvas.drawRect(x,y,xWill,y+lineHeight,xz);
												}else if(index>=selectionEnd&&index<selectionStart){
													canvas.drawRect(x,y,xWill,y+lineHeight,xz);
												}
												x=xwill;
											}
											if(x>drawCache.scrollXMaximum){
												drawCache.scrollXMaximum=x;
											}
										}else{
											break outmost;
										}
									}
								}else{
									if(index==selectionStart){//画光标
										if(index==selectionEnd){
											if(showCursor){
												canvas.drawLine(x,y,x,y+lineHeight,cursor);
											}
										}
									}
									textPaint.setStyle(Paint.Style.FILL);
									textPaint.setColor(currentLineHighlight);
									canvas.drawText(String.format("%03d",line),lineNumberStart,y+jx,hanghao);
									canvas.drawRect(scrollX,y,vw+scrollX,y+lineHeight,textPaint);
									textPaint.setColor(textColor);
									break outmost;
								}
							}
						}
					}else{
						if(index==selectionStart){//画光标
							if(index==selectionEnd){
								if(showCursor){
									canvas.drawLine(x,y,x,y+lineHeight,cursor);
								}
							}
						}
						if(index==selectionEnd){
							textPaint.setStyle(Paint.Style.FILL);
							textPaint.setColor(currentLineHighlight);
							canvas.drawText(String.format("%03d",line),lineNumberStart,y+jx,hanghao);
							canvas.drawRect(scrollX,y,vw+scrollX,y+lineHeight,textPaint);
							textPaint.setColor(textColor);
						}
						break;
					}
				}
			}else{
				outmost://不显示空格字符
				for(int index=drawCache.index;true;index++){//不折行的绘制纯文本
					if(index<text.length){
						if(y<=yInvisible){//字符在视口之外
							char ch=text[index];
							if(ch=='\n'){
								line+=1;
								y+=lineHeight;
								if(ctrl==1){
									ctrl=2;
								}else if(ctrl==3){
									ctrl=4;
								}
							}else if(ch=='<'){
								if(ctrl<0){
									int nn=index+1;
									char cc=text[nn];
									if(cc=='!'){
										if(++nn<text.length){
											cc=text[nn];
											if(cc=='-'){
												if(++nn<text.length){
													cc=text[nn];
													if(cc=='-'){
														ctrl=10;
														textPaint.setColor(commentColor);
													}else{
														ctrl=1;
														textPaint.setColor(tagColor);
													}
												}else{
													ctrl=1;
													textPaint.setColor(tagColor);
												}
											}else{
												ctrl=1;
												textPaint.setColor(tagColor);
											}
										}else{
											ctrl=1;
											textPaint.setColor(tagColor);
										}
									}else{
										ctrl=1;
										textPaint.setColor(tagColor);
									}
									//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
								}
							}else if(ch=='\''){
								if(ctrl==5){
									ctrl=4;
								}else if(ctrl!=0&&ctrl>0&&ctrl!=6&&ctrl<10){
									ctrl=5;
									textPaint.setColor(stringColor);
								}
							}else if(ch=='\"'){
								if(ctrl<10){
									if(ctrl==0){
										ctrl=4;
										//textPaint.setColor(textColor);
									}else if(ctrl>0){
										ctrl=0;
										//textPaint.setColor(stringColor);
										//textPaint.setStyle(Paint.Style.FILL);
									}
								}
							}else if(ch=='>'){
								if(ctrl==14){
									int nn=index-1;
									char cc=text[nn];
									if(cc=='-'){
										if(--nn>=0){
											cc=text[nn];
											if(cc=='-'){
												ctrl=-1;
											}
										}
									}
								}else if(ctrl<10){
									ctrl=-1;
									textPaint.setColor(tagColor);
								}
							}else if(ch=='-'){
								if(ctrl>=10&&ctrl<14){
									ctrl++;
								}
							}else if(ch!=' '&&ch!='\t'){
								if(ctrl==1){ctrl=2;}
								if(ctrl==3){ctrl=4;}
							}else{
								if(ctrl==2||ctrl==1){ctrl=3;}
							}
							continue;
						}else{//字符在视口之内
							if(y>drawCache.scrollYMaximum){
								drawCache.scrollYMaximum=y;
							}
							canvas.drawText(String.format("%03d",line),lineNumberStart,y+jx,hanghao);
							for(;true;index++){//开始绘制文本
								if(index<text.length){
									for(int ii=index;true;ii++){//光标行高亮
										if(ii<text.length){
											char ch=text[ii];
											if(ii>=selectionEnd){
												if(ii==selectionEnd){
													int i=textPaint.getColor();
													textPaint.setStyle(Paint.Style.FILL);
													textPaint.setColor(currentLineHighlight);
													canvas.drawRect(scrollX,y,vw+scrollX,y+lineHeight,textPaint);
													textPaint.setColor(i);
												}
												for(;true;index++){//画出余下行
												//log.alert("ctrl:"+ctrl);
													if(index==selectionStart){//画光标
														if(index==selectionEnd){
															if(showCursor){
																canvas.drawLine(x,y,x,y+lineHeight,cursor);
															}
														}
													}
													if(index<text.length){
														ch=text[index];
														int xWill=0;
														if(ch=='\n'){
															line++;
															y+=lineHeight;
															x=primex;
															canvas.drawText(String.format("%03d",line),lineNumberStart,y+jx,hanghao);
															if(ctrl==1){
																ctrl=2;
															}else if(ctrl==3){
																ctrl=4;
															}
															int yy=y+lineHeight;
															if(yy>drawCache.scrollYMaximum){
																drawCache.scrollYMaximum=yy;
															}
															if(y>=yOverflowMin){
																break outmost;
															}
														}else if(ch=='\t'){
															xWill=((x-primex)/tablen+1)*tablen+primex;
															x=xWill;
															if(ctrl==1){
																ctrl=2;
															}else if(ctrl==3){
																ctrl=4;
															}
														}else if(ch==' '){
															xWill=x+textWS[index];
															x=xWill;
															if(ctrl==1){
																ctrl=2;
															}else if(ctrl==3){
																ctrl=4;
															}
														}else{
															if(ch=='='){
																if(ctrl==1||ctrl==2||ctrl==3||ctrl==4){
																	textPaint.setColor(tagColor);
																	//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
																}
															}else if(ch=='-'){
																if(ctrl>=10&&ctrl<14){
																	ctrl++;
																}
															}else if(ch=='<'){
																if(ctrl<0){
																	int nn=index+1;
																	char cc=text[nn];
																	if(cc=='!'){
																		if(++nn<text.length){
																			cc=text[nn];
																			if(cc=='-'){
																				if(++nn<text.length){
																					cc=text[nn];
																					if(cc=='-'){
																						ctrl=10;
																						textPaint.setColor(commentColor);
																					}else{
																						ctrl=1;
																						textPaint.setColor(tagColor);
																					}
																				}else{
																					ctrl=1;
																					textPaint.setColor(tagColor);
																				}
																			}else{
																				ctrl=1;
																				textPaint.setColor(tagColor);
																			}
																		}else{
																			ctrl=1;
																			textPaint.setColor(tagColor);
																		}
																	}else{
																		ctrl=1;
																		textPaint.setColor(tagColor);
																	}
																	//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
																}
															}else if(ch=='>'){
																if(ctrl==14){
																	int nn=index-1;
																	char cc=text[nn];
																	if(cc=='-'){
																		if(--nn>=0){
																			cc=text[nn];
																			if(cc=='-'){
																				ctrl=-1;
																				int advance=textWS[index];
																				xWill=x+advance;
																				canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
																				x=xWill;
																				textPaint.setColor(textColor);
																				continue;
																			}
																		}
																	}
																}else if(ctrl<10){
																	ctrl=-1;
																	int advance=textWS[index];
																	xWill=x+advance;
																	textPaint.setColor(tagColor);
																	canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
																	x=xWill;
																	textPaint.setColor(textColor);
																	continue;
																}
																//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
															}else if(ch=='\"'){
																if(ctrl<10){
																	if(ctrl==0){
																		ctrl=4;
																		int advance=textWS[index];
																		xWill=x+advance;
																		canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
																		x=xWill;
																		textPaint.setColor(textColor);
																		continue;
																		//textPaint.setColor(textColor);
																	}else if(ctrl>0&&ctrl!=5&&ctrl!=6){
																		ctrl=0;
																		textPaint.setColor(stringColor);
																		//textPaint.setStyle(Paint.Style.FILL);
																	}
																}
															}else if(ch=='\''){
																if(ctrl==5){
																	ctrl=4;
																	int advance=textWS[index];
																	xWill=x+advance;
																	canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
																	x=xWill;
																	textPaint.setColor(textColor);
																	continue;
																}else if(ctrl!=0&&ctrl>0&&ctrl!=6&&ctrl<10){
																	ctrl=5;
																	textPaint.setColor(stringColor);
																}
															}else if(ch=='/'){
																if(ctrl<10){
																	if(ctrl>0&&ctrl!=6&&ctrl!=5){
																		textPaint.setColor(tagColor);
																		//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
																	}
																}
															}else if(ctrl<0){
																textPaint.setColor(textColor);
																//textPaint.setStyle(Paint.Style.FILL);
															}else if(ctrl==1){
																ctrl=3;
																textPaint.setColor(tagColor);
																//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
															}else if(ctrl==2){
																ctrl=3;
																textPaint.setColor(tagColor);
																//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
															}else if(ctrl==3){
																textPaint.setColor(tagColor);
																//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
															}else if(ctrl==4){
																textPaint.setColor(textColor);
																//textPaint.setStyle(Paint.Style.FILL);
															}
															int advance=textWS[index];
															xWill=x+advance;
															canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
															x=xWill;
														}
														if(x>drawCache.scrollXMaximum){
															drawCache.scrollXMaximum=x;
														}
													}else{
														break;
													}
												}
												break outmost;
											}else if(ch=='\n'){
												break;
											}
										}else{//默认光标在最后一行
											textPaint.setStyle(Paint.Style.FILL);
											textPaint.setColor(currentLineHighlight);
											canvas.drawRect(scrollX,y,vw+scrollX,y+lineHeight,textPaint);
											textPaint.setColor(textColor);
											break;
										}
									}
									for(;true;index++){//画出一行
										if(index==selectionStart){//画光标
											if(index==selectionEnd){
												if(showCursor){
													canvas.drawLine(x,y,x,y+lineHeight,cursor);
												}
											}
										}
										if(index<text.length){
											char ch=text[index];
											if(ch=='\n'){
												line++;
												y+=lineHeight;
												x=primex;
												canvas.drawText(String.format("%03d",line),lineNumberStart,y+jx,hanghao);
												int yy=y+lineHeight;
												if(yy>drawCache.scrollYMaximum){
													drawCache.scrollYMaximum=yy;
												}
												if(ctrl==1){
													ctrl=2;
												}else if(ctrl==3){
													ctrl=4;
												}
												if(y>=yOverflowMin){
													break outmost;
												}
												break;
											}else if(ch=='\t'){
												int xWill=((x-primex)/tablen+1)*tablen+primex;
												x=xWill;
											}else if(ch==' '){
												int xWill=x+textWS[index];
												x=xWill;
												if(ctrl==1){
													ctrl=2;
												}else if(ctrl==3){
													ctrl=4;
												}
											}else{
												if(ch=='='){
													if(ctrl==1||ctrl==2||ctrl==3||ctrl==4){
														textPaint.setColor(tagColor);
														//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
													}
												}else if(ch=='-'){
													if(ctrl>=10&&ctrl<14){
														ctrl++;
													}
												}else if(ch=='<'){
													if(ctrl<0){
														int nn=index+1;
														char cc=text[nn];
														if(cc=='!'){
															if(++nn<text.length){
																cc=text[nn];
																if(cc=='-'){
																	if(++nn<text.length){
																		cc=text[nn];
																		if(cc=='-'){
																			ctrl=10;
																			textPaint.setColor(commentColor);
																		}else{
																			ctrl=1;
																			textPaint.setColor(tagColor);
																		}
																	}else{
																		ctrl=1;
																		textPaint.setColor(tagColor);
																	}
																}else{
																	ctrl=1;
																	textPaint.setColor(tagColor);
																}
															}else{
																ctrl=1;
																textPaint.setColor(tagColor);
															}
														}else{
															ctrl=1;
															textPaint.setColor(tagColor);
														}
														//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
													}
												}else if(ch=='>'){
													if(ctrl==14){
														int nn=index-1;
														char cc=text[nn];
														if(cc=='-'){
															if(--nn>=0){
																cc=text[nn];
																if(cc=='-'){
																	ctrl=-1;
																	int advance=textWS[index];
																	int xWill=x+advance;
																	canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
																	x=xWill;
																	textPaint.setColor(textColor);
																	continue;
																}
															}
														}
													}else if(ctrl<10){
														ctrl=-1;
														int advance=textWS[index];
														int xWill=x+advance;
														textPaint.setColor(tagColor);
														canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
														x=xWill;
														textPaint.setColor(textColor);
														continue;
													}
													//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
												}else if(ch=='\"'){
													if(ctrl<10){
														if(ctrl==0){
															ctrl=4;
															int advance=textWS[index];
															int xWill=x+advance;
															canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
															x=xWill;
															textPaint.setColor(textColor);
															continue;
															//textPaint.setColor(textColor);
														}else if(ctrl>0&&ctrl!=5&&ctrl!=6){
															ctrl=0;
															textPaint.setColor(stringColor);
															//textPaint.setStyle(Paint.Style.FILL);
														}
													}
												}else if(ch=='\''){
													if(ctrl==5){
														ctrl=4;
														int advance=textWS[index];
														int xWill=x+advance;
														canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
														x=xWill;
														textPaint.setColor(textColor);
														continue;
													}else if(ctrl!=0&&ctrl>0&&ctrl!=6&&ctrl<10){
														ctrl=5;
														textPaint.setColor(stringColor);
													}
												}else if(ch=='/'){
													if(ctrl<10){
														if(ctrl>0&&ctrl!=6&&ctrl!=5){
															textPaint.setColor(tagColor);
															//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
														}
													}
												}else if(ctrl<0){
													textPaint.setColor(textColor);
													//textPaint.setStyle(Paint.Style.FILL);
												}else if(ctrl==1){
													ctrl=3;
													textPaint.setColor(tagColor);
													//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
												}else if(ctrl==2){
													ctrl=3;
													textPaint.setColor(tagColor);
													//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
												}else if(ctrl==3){
													textPaint.setColor(tagColor);
													//textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
												}else if(ctrl==4){
													textPaint.setColor(textColor);
													//textPaint.setStyle(Paint.Style.FILL);
												}
												int advance=textWS[index];
												int xWill=x+advance;
												canvas.drawText(Character.toString(ch),x,y+baseline,textPaint);
												x=xWill;
											}
											if(x>drawCache.scrollXMaximum){
												drawCache.scrollXMaximum=x;
											}
										}else{
											break outmost;
										}
									}
								}else{
									if(index==selectionStart){//画光标
										if(index==selectionEnd){
											if(showCursor){
												canvas.drawLine(x,y,x,y+lineHeight,cursor);
											}
										}
									}
									textPaint.setStyle(Paint.Style.FILL);
									textPaint.setColor(currentLineHighlight);
									canvas.drawText(String.format("%03d",line),lineNumberStart,y+jx,hanghao);
									canvas.drawRect(scrollX,y,vw+scrollX,y+lineHeight,textPaint);
									textPaint.setColor(textColor);
									break outmost;
								}
							}
						}
					}else{
						if(index==selectionStart){//画光标
							if(index==selectionEnd){
								if(showCursor){
									canvas.drawLine(x,y,x,y+lineHeight,cursor);
								}
							}
						}
						if(index==selectionEnd){
							textPaint.setStyle(Paint.Style.FILL);
							textPaint.setColor(currentLineHighlight);
							canvas.drawText(String.format("%03d",line),lineNumberStart,y+jx,hanghao);
							canvas.drawRect(scrollX,y,vw+scrollX,y+lineHeight,textPaint);
							textPaint.setColor(textColor);
						}
						break;
					}
				}
			}
		}else{
			int textColorSaved=textPaint.getColor();
			textPaint.setColor(0xff777777);
			canvas.drawText("Null",getPaddingLeft(),getPaddingTop()+lineHeight,textPaint);
			textPaint.setColor(textColorSaved);
		}
	}
	public void moveSelection(int a,int b){
		final int selectionStartWill=selectionStart+a;
		final int selectionEndWill=selectionEnd+b;
		if(selectionStartWill>=0&&selectionStartWill<=text.length){
			selectionStart=selectionStartWill;
		}
		if(selectionEndWill>=0&&selectionEndWill<=text.length){
			selectionEnd=selectionEndWill;
		}
	}
	class InertiaScroll extends Thread{
		int orientation;
		double initialSpeed;
		double minSpeed=0.001;
		double inertia;
		int initialScrollX;
		int initialScrollY;
		InertiaScroll(){
			inertia=0.0005;//(10*ma.dp)/1000;
		}
		@Override
		public void run(){
			super.run();
			long initialTime=System.currentTimeMillis();
			long dt;
			if(orientation==0){
				int scrollXWill;
				int scrollXSaved=initialScrollX;
				if(initialSpeed<0){
					//log.alert("<0");
					try{
						sleep(1);
					}catch(Exception e){}
					while(!interrupted()){
						dt=System.currentTimeMillis()-initialTime;
						double speedNow=initialSpeed+inertia*dt;
						if(speedNow<-minSpeed){
							//scrollXWill=initialScrollX-(int)(initialSpeed*dTime+inertia*dTime*dTime/2);
							scrollXWill=initialScrollX-(int)((initialSpeed+(inertia*dt)/2)*dt);
							if(scrollXWill>scrollXSaved){
								post(new LetScroll(scrollXWill,initialScrollY));
							}
							scrollXSaved=scrollXWill;
						}else{
							break;
						}
					}
				}else if(initialSpeed>0){
					try{
						sleep(1);
					}catch(Exception e){}
					while(!interrupted()){
						dt=System.currentTimeMillis()-initialTime;
						double speedNow=initialSpeed-inertia*dt;
						if(speedNow>minSpeed){
							scrollXWill=initialScrollX-(int)(initialSpeed*dt-inertia*dt*dt/2);
							//scrollXWill=initialScrollX-(int)((initialSpeed-(inertia*dTime)/2)*dTime);
							if(scrollXWill<scrollXSaved){
								if(scrollXWill<=0){
									post(new LetScroll(0,initialScrollY));
									return;
								}
								post(new LetScroll(scrollXWill,initialScrollY));
							}
							scrollXSaved=scrollXWill;
						}else{
							break;
						}
					}
				}else{
					return;
				}
			}else if(orientation==1){
				if(initialSpeed<0){
					try{
						sleep(1);
					}catch(Exception e){}
					int scrollYSaved=initialScrollY;
					//log.alert("上滑");
					while(!interrupted()){
						dt=System.currentTimeMillis()-initialTime;
						double speedNow=initialSpeed+inertia*dt;
						if(speedNow<-minSpeed){
							//int scrollYWill=initialScrollY-(int)(initialSpeed*dTime+inertia*dTime*dTime/2);
							int scrollYWill=initialScrollY-(int)((initialSpeed+(inertia*dt)/2)*dt);
							if(scrollYWill>scrollYSaved){
								if(scrollYWill>=drawCache.scrollYMaximum){
									post(new LetScroll(initialScrollX,drawCache.scrollYMaximum));
									return;
								}
								post(new LetScroll(initialScrollX,scrollYWill));
							}
							scrollYSaved=scrollYWill;
						}else{
							break;
						}
					}
				}else if(initialSpeed>0){
					try{
						sleep(1);
					}catch(Exception e){}
					int scrollYSaved=initialScrollY;
					while(!interrupted()){
						dt=System.currentTimeMillis()-initialTime;
						double speedNow=initialSpeed-inertia*dt;
						if(speedNow>minSpeed){
							int scrollYWill=initialScrollY-(int)((initialSpeed-(inertia*dt)/2)*dt);
							if(scrollYWill<scrollYSaved){
								if(scrollYWill<=0){
									post(new LetScroll(initialScrollX,0));
									return;
								}
								post(new LetScroll(initialScrollX,scrollYWill));
							}
							scrollYSaved=scrollYWill;
						}else{
							break;
						}
					}
				}else return;
			}else return;
		}
		class LetScroll implements Runnable{
			int x,y;
			LetScroll(int x,int y){
				this.x=x;
				this.y=y;
			}
			@Override
			public void run(){
				scrollX=x;
				scrollY=y;
				invalidate();
			}
		}
	}
	class WaitLongClick extends Thread{
		int interval=400;
		Point lastTouch=new Point();
		volatile boolean waited=false;
		@Override
		public void run(){
			super.run();
			try{
				sleep(interval);
			}catch(Exception e){}
			if(waited){
				return;
			}else
			waited=true;
			if(fingerPressed&&!fingerMoved){
				post(new Runnable(){
					@Override
					public void run(){
						if(selectionStart!=selectionEnd&&ma.gui.batch.getVisibility()!=View.VISIBLE){
							ma.gui.removeViewAt(ma.gui.titleIndex);
                            ma.gui.addView(ma.gui.batch,ma.gui.titleIndex,ma.gui.titlebarlp);
						}else{
							int titleIndex=ma.gui.titleIndex;
                            if(ma.gui.getChildAt(titleIndex)==ma.gui.batch){
                                ma.gui.removeViewAt(titleIndex);
                                ma.gui.addView(ma.gui.titlebar,titleIndex);
                            }
							final int tablen=(int)textPaint.measureText(tabWidth);
							final int px=lastTouch.x+scrollX;
							final int py=lastTouch.y+scrollY;
							//计算手指按住的是哪个字符，并选中
							for(int index=0,x=getPaddingRight(),y=getPaddingTop(),glyph=0;true;index++,glyph++){
								if(index<text.length){
									char ch=text[index];
									if(ch=='\\'){
										if(++index<text.length){
											ch=text[index];
											if(ch=='p'){
												if(++index<text.length){
													ch=text[index];
													int w=ch>>>8;
													int h=ch&0x00ff;
													int outWidth=w*lineHeight/h;
													int xwill=x+outWidth;
													if((index+=w*h)<text.length){
														if(px>=x&&px<xwill&&py>=y&&py<y+lineHeight){
															selectionStart=glyph;
															selectionEnd=glyph+1;
															invalidate();
															break;
														}
														x=xwill;
													}else{
														if(px>=x&&px<xwill&&py>=y&&py<y+lineHeight){
															selectionStart=glyph;
															selectionEnd=glyph+1;
															invalidate();
															break;
														}else if(px>=xwill&&py>=y&&py<y+lineHeight){
															selectionStart=glyph+1;
															selectionEnd=glyph+1;
															invalidate();
														}
														x=xwill;
														break;
													}
												}else{
													break;
												}
											}else if(ch=='\\'){
												int advance=textWS[glyph];
												int xwill=x+advance;
												if(px>=x&&px<xwill&&py>=y&&py<y+lineHeight){
													selectionStart=glyph;
													selectionEnd=glyph+1;
													invalidate();
													break;
												}
												x=xwill;
											}else{
												index--;
												continue;
											}
										}else{
											int advance=textWS[glyph];
											int xwill=x+advance;
											if(px>=x&&px<xwill&&py>=y&&py<y+lineHeight){
												selectionStart=glyph;
												selectionEnd=glyph+1;
												invalidate();
											}else if(px>=xwill&&py>=y&&py<y+lineHeight){
												selectionStart=glyph+1;
												selectionEnd=glyph+1;
												invalidate();
											}
											break;
										}
									}else if(ch=='\t'){
										int xwill=((x-getPaddingLeft())/tablen+1)*tablen;
										if(px>=x&&px<xwill&&py>=y&&py<y+lineHeight){
											selectionStart=glyph;
											selectionEnd=glyph+1;
											invalidate();
											break;
										}
										x=xwill;
									}else if(ch=='\n'){
										int ywill=y+lineHeight;
										if(px>=x&&py>=y&&py<y+lineHeight){
											selectionStart=glyph;
											selectionEnd=glyph;
											break;
										}
										x=getPaddingLeft();
										y=ywill;
									}else{
										int advance=textWS[glyph];
										int xwill=x+advance;
										if(px>=x&&px<xwill&&py>=y&&py<y+lineHeight){
											selectionStart=glyph;
											selectionEnd=glyph+1;
											invalidate();
											break;
										}
										x=xwill;
									}
								}else{
									if(px>=x&&py>=y){
										selectionStart=glyph;
										selectionEnd=glyph;
										invalidate();
									}
									break;
								}
							}
						}
					}
				});
			}
		}
	}
	public class IC extends BaseInputConnection{
		IC(View v,boolean b){
			super(v,b);
		}
		@Override
		public boolean setComposingText(CharSequence text,int newCursorPosition){
			return false;
		}
		@Override
		public boolean commitText(CharSequence txt,int newCursorPosition){
			//log.alert("cursor:"+newCursorPosition);
			String text=txt.toString();
			if(ma.gui.ebi.capsLock){
				text=text.toUpperCase();
			}
			if(text.toString().equals("\n")){
				if(selectionStart==selectionEnd){
					String insert="\n";
					//0log.alert("start:"+selectionStart);
					for(int index=selectionStart-1;true;index-=1){
						if(index>=0){
							char ch=HtmlIndentEditor.this.text[index];
							if(ch=='\n'){
								break;
							}else if(ch=='\t'){
								insert=insert+'\t';
							}else{
								insert="\n";
							}
						}else{break;}
					}
					repl(selectionStart,selectionStart,insert.toCharArray());
					selectionStart=selectionStart+insert.length()-1+newCursorPosition;
					selectionEnd=selectionStart;
				}
			}else{
				repl(selectionStart,selectionEnd,text.toString().toCharArray());
				selectionStart=selectionStart+text.length()-1+newCursorPosition;
				selectionEnd=selectionStart;
			}
			if(text.length()>0){
				ma.gui.ivSave.setColorFilter(null);
				ma.gui.ivSave.invalidate();
				ma.gui.ivRefresh.setColorFilter(null);
				ma.gui.ivRefresh.invalidate();
                int titleIndex=ma.gui.titleIndex;
                if(ma.gui.getChildAt(titleIndex)==ma.gui.batch){
                    ma.gui.removeViewAt(titleIndex);
                    ma.gui.addView(ma.gui.titlebar,titleIndex);
                }
			}
			if(ma.gui.tfNow instanceof FileBrowserTab){
				if(text.length()>0){
					FileBrowserTab fbt=(FileBrowserTab)ma.gui.tfNow;
					FileBrowserPage fbp=fbt.fileBrowserPage;
					fbp.editorCanSave=true;
				}
			}else if(ma.gui.tfNow instanceof HtmlEditorTab){
				if(text.length()>0){
					HtmlEditorTab h=(HtmlEditorTab)ma.gui.tfNow;
					h.canSave=true;
					h.setTextColor(0xffff0000);
				}
			}
			return true;
		}
		@Override
		public boolean deleteSurroundingText(int beforeLength,int afterLength){
			int a,b;
			if(selectionStart<=selectionEnd){
				a=selectionStart-beforeLength;
				b=selectionEnd+afterLength;
			}else{
				a=selectionEnd-beforeLength;
				b=selectionStart+afterLength;
			}
			boolean modified=false;
			if(a<0){
				a=0;
			}
			if(b>=text.length){
				b=text.length;
			}
			if(a!=b)modified=true;
			repl(a,b,null);
			showCursor=true;
			tcv.againWait=true;
			tcv.interrupt();
			HtmlIndentEditor.this.letSelection(a);
			invalidate();
			if(modified){
                int titleIndex=ma.gui.titleIndex;
                if(ma.gui.getChildAt(titleIndex)==ma.gui.batch){
                    ma.gui.removeViewAt(titleIndex);
                    ma.gui.addView(ma.gui.titlebar,titleIndex);
                }
				if(ma.gui.tfNow instanceof HtmlEditorTab){
					HtmlEditorTab h=(HtmlEditorTab)ma.gui.tfNow;
					h.canSave=true;
					h.setTextColor(0xffff0000);
					ma.gui.ivSave.setColorFilter(null);
					ma.gui.ivSave.invalidate();
					ma.gui.ivRefresh.setColorFilter(null);
					ma.gui.ivRefresh.invalidate();
				}else if(ma.gui.tfNow instanceof FileBrowserTab){
					FileBrowserTab fbt=(FileBrowserTab)ma.gui.tfNow;
					FileBrowserPage fbp=fbt.fileBrowserPage;
					fbp.editorCanSave=true;
					ma.gui.ivSave.setColorFilter(null);
					ma.gui.ivSave.invalidate();
					ma.gui.ivRefresh.setColorFilter(null);
					ma.gui.ivRefresh.invalidate();
				}
			}
			return true;
		}
		@Override
		public boolean sendKeyEvent(KeyEvent event){
			//log.alert("2333");
			if(event.getAction()==KeyEvent.ACTION_DOWN){
				int keycode=event.getKeyCode();
				switch(keycode){
					case KeyEvent.KEYCODE_ENTER:
						commitText("\n",1);
						break;
					case KeyEvent.KEYCODE_DPAD_LEFT:
						if(ma.gui.batch.getVisibility()==View.VISIBLE){
							moveSelection(0,-1);
							showCursor=true;
							tcv.againWait=true;
							tcv.interrupt();
							invalidate();
						}else if(selectionStart==selectionEnd){
							moveSelection(-1,-1);
							invalidate();
						}
						break;
					case KeyEvent.KEYCODE_DPAD_RIGHT:
						if(ma.gui.batch.getVisibility()==View.VISIBLE){
							moveSelection(0,1);
							invalidate();
						}else if(selectionStart==selectionEnd){
							moveSelection(1,1);
							showCursor=true;
							tcv.againWait=true;
							tcv.interrupt();
							invalidate();
						}
						break;
					case KeyEvent.KEYCODE_DPAD_UP:
						break;
					case KeyEvent.KEYCODE_DPAD_DOWN:
						break;
					case KeyEvent.KEYCODE_DEL:
						deleteSurroundingText(1,0);
						break;
					default:
						char keyChar=(char)keycode;
						commitText(Character.toString(keyChar),1);
				}
			}
			return true;
		}
		@Override
		public boolean setSelection(int start,int end){
			return false;
		}
	}
}
